home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 93 / applic / sdbio.c < prev    next >
C/C++ Source or Header  |  1987-01-15  |  11KB  |  435 lines

  1. /* SDB - relation file I/O routines */
  2.  
  3. #include "sdbio.h"
  4.  
  5. /* global error code variable */
  6. int dbv_errcode;
  7.  
  8. /* list of currently loaded relation definitions */
  9. static struct relation *relations = NULL;
  10.  
  11. /* external routines */
  12. extern long lseek();
  13.  
  14. /* forward declarations */
  15. static struct relation *rfind();
  16.  
  17. /* db_ropen - open a relation file */
  18. struct scan *db_ropen(rname)
  19.   char *rname;
  20. {
  21.     struct relation *rptr;
  22.     struct scan *sptr;
  23.     char filename[RNSIZE+5];
  24.  
  25.     /* find the relation definition */
  26.     if ((rptr = rfind(rname)) == NULL)
  27.         return (NULL);
  28.  
  29.     /* allocate a new scan structure */
  30.     if ((sptr = (struct scan *)malloc(sizeof(struct scan))) == NULL)
  31.         return (db_nerror(INSMEM));
  32.  
  33.     /* allocate a tuple buffer */
  34.     if ((sptr->sc_tuple = malloc(rptr->rl_size)) == NULL) {
  35.         free(sptr);
  36.         return (db_nerror(INSMEM));
  37.     }
  38.  
  39.     /* initialize the scan structure */
  40.     sptr->sc_relation = rptr;        /* store the relation struct addrs */
  41.     sptr->sc_dtnum = 0;            /* desired tuple (non-existant) */
  42.     sptr->sc_atnum = 0;            /* actual tuple (non-existant) */
  43.     sptr->sc_store = FALSE;        /* no store done since open */
  44.  
  45.     /* open relation file if necessary */
  46.     if (rptr->rl_scnref++ == 0) {
  47.  
  48.         /* create the relation file name */
  49.         make_fname(filename,rname);
  50.  
  51.         /* open the relation file */
  52.         if ((rptr->rl_fd = open(filename,2)) == -1) {
  53.             rptr->rl_scnref--;
  54.             free(sptr->sc_tuple); free(sptr);
  55.             return (db_nerror(RELFNF));
  56.         }
  57.     }
  58.  
  59.     /* return the new scan structure pointer */
  60.     return (sptr);
  61. }
  62.  
  63. /* db_rclose - close the relation file */
  64. int db_rclose(sptr)
  65.   struct scan *sptr;
  66. {
  67.     struct relation *rptr,*lastrptr;
  68.  
  69.     /* close relation file if this is the last reference */
  70.     if (--sptr->sc_relation->rl_scnref == 0) {
  71.  
  72.         /* rewrite header if any stores took place */
  73.         if (sptr->sc_store) {
  74.  
  75.             /* store the tuple count back in the header */
  76.             db_cvbytes(sptr->sc_relation->rl_tcnt,
  77.                sptr->sc_relation->rl_header.hd_tcnt);
  78.  
  79.             /* write the header block */
  80.             if (lseek(sptr->sc_relation->rl_fd,0L,0) != 0L
  81.             ||  write(sptr->sc_relation->rl_fd,
  82.                   &sptr->sc_relation->rl_header,512) != 512) {
  83.             close(sptr->sc_relation->rl_fd);
  84.             free(sptr->sc_tuple); free(sptr);
  85.             return (db_ferror(BADHDR));
  86.             }
  87.         }
  88.  
  89.         /* close the relation file */
  90.         close(sptr->sc_relation->rl_fd);
  91.  
  92.         /* free the relation header */
  93.         lastrptr = NULL;
  94.         for (rptr = relations; rptr != NULL; rptr = rptr->rl_next) {
  95.             if (rptr == sptr->sc_relation) {
  96.             if (lastrptr == NULL)
  97.                 relations = rptr->rl_next;
  98.             else
  99.                 lastrptr->rl_next = rptr->rl_next;
  100.          }
  101.             lastrptr = rptr;
  102.         }
  103.         free(sptr->sc_relation);
  104.     }
  105.  
  106.     /* free the scan structure */
  107.     free(sptr->sc_tuple); free(sptr);
  108.  
  109.     /* return successfully */
  110.     return (TRUE);
  111. }
  112.  
  113. /* db_rcompress - compress a relation file */
  114. int db_rcompress(sptr)
  115.   struct scan *sptr;
  116. {
  117.     unsigned int next,nextfree,tcnt;
  118.  
  119.     /* get the last used tuple */
  120.     tcnt = sptr->sc_relation->rl_tcnt;
  121.  
  122.     /* loop through all of the tuples */
  123.     for (next = nextfree = 1; next <= tcnt; next++) {
  124.  
  125.         /* read the tuple */
  126.         if (!seek(sptr->sc_relation,next)
  127.         ||  read(sptr->sc_relation->rl_fd,
  128.               sptr->sc_tuple,sptr->sc_relation->rl_size)
  129.                 != sptr->sc_relation->rl_size)
  130.             return (db_ferror(TUPINP));
  131.  
  132.     /* rewrite the tuple if it is active */
  133.         if (sptr->sc_tuple[0] == ACTIVE) {
  134.  
  135.         /* rewrite it only if it must move */
  136.         if (next != nextfree) {
  137.  
  138.         /* write the tuple */
  139.         if (!seek(sptr->sc_relation,nextfree)
  140.         ||  write(sptr->sc_relation->rl_fd,
  141.                sptr->sc_tuple,sptr->sc_relation->rl_size)
  142.                 != sptr->sc_relation->rl_size)
  143.             return (db_ferror(TUPOUT));
  144.         }
  145.  
  146.         /* update the next free tuple number */
  147.         nextfree += 1;
  148.     }
  149.     }
  150.  
  151.     /* update the tuple count */
  152.     sptr->sc_relation->rl_tcnt = nextfree - 1;
  153.  
  154.     /* remember which tuple is in the buffer */
  155.     sptr->sc_atnum = sptr->sc_relation->rl_tcnt;
  156.  
  157.     /* reset the desired tuple */
  158.     sptr->sc_dtnum = 0;
  159.  
  160.     /* remember that the index needs rewriting */
  161.     sptr->sc_store = TRUE;
  162.  
  163.     /* return successfully */
  164.     return (TRUE);
  165. }
  166.  
  167. /* db_rbegin - begin scan at first tuple in relation */
  168. db_rbegin(sptr)
  169.   struct scan *sptr;
  170. {
  171.     /* begin with the first tuple in the file */
  172.     sptr->sc_dtnum = 0;
  173. }
  174.  
  175. /* db_rfetch - fetch the next tuple from the relation file */
  176. int db_rfetch(sptr)
  177.   struct scan *sptr;
  178. {
  179.     /* look for an active tuple */
  180.     while (TRUE) {
  181.  
  182.     /* get the tuple if its not already in the buffer */
  183.     if (sptr->sc_dtnum+1 != sptr->sc_atnum)
  184.         if (!db_rget(sptr,sptr->sc_dtnum+1,sptr->sc_tuple))
  185.         return (FALSE);
  186.  
  187.         /* increment the tuple number */
  188.         sptr->sc_dtnum += 1;
  189.  
  190.     /* remember which tuple is in the buffer */
  191.     sptr->sc_atnum = sptr->sc_dtnum;
  192.  
  193.         /* return if the tuple found is active */
  194.         if (sptr->sc_tuple[0] == ACTIVE)
  195.             return (TRUE);
  196.     }
  197. }
  198.  
  199. /* db_rupdate - update the current tuple */
  200. int db_rupdate(sptr)
  201.   struct scan *sptr;
  202. {
  203.     /* make sure the status byte indicates an active tuple */
  204.     sptr->sc_tuple[0] = ACTIVE;
  205.  
  206.     /* write the tuple */
  207.     return (db_rput(sptr,sptr->sc_atnum,sptr->sc_tuple));
  208. }
  209.  
  210. /* db_rdelete - delete the current tuple */
  211. int db_rdelete(sptr)
  212.   struct scan *sptr;
  213. {
  214.     /* make sure the status byte indicates a deleted tuple */
  215.     sptr->sc_tuple[0] = DELETED;
  216.  
  217.     /* write the tuple */
  218.     return (db_rput(sptr,sptr->sc_atnum,sptr->sc_tuple));
  219. }
  220.  
  221. /* db_rstore - store a new tuple */
  222. int db_rstore(sptr)
  223.   struct scan *sptr;
  224. {
  225.     /* make sure there's room for this tuple */
  226.     if (sptr->sc_relation->rl_tcnt == sptr->sc_relation->rl_tmax)
  227.     if (!db_rextend(sptr))
  228.         return (FALSE);
  229.  
  230.     /* make sure the status byte indicates an active tuple */
  231.     sptr->sc_tuple[0] = ACTIVE;
  232.  
  233.     /* write the tuple */
  234.     if (!db_rput(sptr,sptr->sc_relation->rl_tcnt + 1,sptr->sc_tuple))
  235.         return (FALSE);
  236.  
  237.     /* update the tuple count */
  238.     sptr->sc_relation->rl_tcnt += 1;
  239.  
  240.     /* remember which tuple is in the buffer */
  241.     sptr->sc_atnum = sptr->sc_relation->rl_tcnt;
  242.  
  243.     /* remember that a tuple was stored */
  244.     sptr->sc_store = TRUE;
  245.  
  246.     /* return successfully */
  247.     return (TRUE);
  248. }
  249.  
  250. /* db_rget - get a tuple from the relation file */
  251. int db_rget(sptr,tnum,buf)
  252.   struct scan *sptr; unsigned int tnum; char *buf;
  253. {
  254.     /* check for this being beyond the last tuple */
  255.     if (tnum > sptr->sc_relation->rl_tcnt)
  256.         return (db_ferror(TUPINP));
  257.  
  258.     /* read the tuple */
  259.     if (!seek(sptr->sc_relation,tnum)
  260.     ||  read(sptr->sc_relation->rl_fd,buf,sptr->sc_relation->rl_size)
  261.             != sptr->sc_relation->rl_size)
  262.         return (db_ferror(TUPINP));
  263.  
  264.     /* return successfully */
  265.     return (TRUE);
  266. }
  267.  
  268. /* db_rput - put a tuple to a relation file */
  269. int db_rput(sptr,tnum,buf)
  270.   struct scan *sptr; unsigned int tnum; char *buf;
  271. {
  272.     /* check for this being beyond the maximum tuple */
  273.     if (tnum > sptr->sc_relation->rl_tmax)
  274.         return (db_ferror(TUPOUT));
  275.  
  276.     /* write the tuple */
  277.     if (!seek(sptr->sc_relation,tnum)
  278.     ||  write(sptr->sc_relation->rl_fd,buf,sptr->sc_relation->rl_size)
  279.         != sptr->sc_relation->rl_size)
  280.     return (db_ferror(TUPOUT));
  281.  
  282.     /* return successfully */
  283.     return (TRUE);
  284. }
  285.  
  286. /* db_rextend - extend a relation file */
  287. int db_rextend(sptr)
  288.   struct scan *sptr;
  289. {
  290.     struct relation *rptr;
  291.     unsigned int n,i;
  292.     char *tbuf;
  293.  
  294.     /* get the relation pointer */
  295.     rptr = sptr->sc_relation;
  296.  
  297.     /* make sure we can extend this relation */
  298.     if ((n = rptr->rl_text) == 0)
  299.     return (db_ferror(RELFUL));
  300.  
  301.     /* seek to the correct place in the file */
  302.     if (!seek(rptr,rptr->rl_tmax+1))
  303.     return (db_ferror(TUPOUT));
  304.  
  305.     /* allocate a tuple buffer */
  306.     if ((tbuf = calloc(1,rptr->rl_size)) == NULL)
  307.     return (db_ferror(INSMEM));
  308.  
  309.     /* write null tuples into the file */
  310.     for (i = 0; i < n; i++)
  311.     if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
  312.         free(tbuf);
  313.         return (db_ferror(INSBLK));
  314.     }
  315.  
  316.     /* free the tuple buffer */
  317.     free(tbuf);
  318.  
  319.     /* update the relation size */
  320.     rptr->rl_tmax += n;
  321.     db_cvbytes(rptr->rl_tmax,rptr->rl_header.hd_tmax);
  322.  
  323.  
  324.     /* remember that the header was changed */
  325.     sptr->sc_store = TRUE;
  326.  
  327.     /* return successfully */
  328.     return (TRUE);
  329. }
  330.  
  331. /* rfind - find the specified relation */
  332. static struct relation *rfind(rname)
  333.   char *rname;
  334. {
  335.     int fd;
  336.     char filename[RNSIZE+5];
  337.     struct relation *rptr;
  338.  
  339.     /* look for relation in list currently loaded */
  340.     for (rptr = relations; rptr != NULL; rptr = rptr->rl_next)
  341.     if (db_sncmp(rname,rptr->rl_name,RNSIZE) == 0)
  342.         return (rptr);
  343.  
  344.     /* create a file name */
  345.     make_fname(filename,rname);
  346.  
  347.     /* lookup the relation file */
  348.     if ((fd = open(filename,0)) == -1)
  349.     return (db_nerror(RELFNF));
  350.  
  351.     /* allocate a new relation structure */
  352.     if ((rptr = (struct relation *)malloc(sizeof(struct relation))) == NULL) {
  353.         close(fd);
  354.         return (db_nerror(INSMEM));
  355.     }
  356.  
  357.     /* initialize the relation structure */
  358.     rptr->rl_scnref = 0;
  359.  
  360.     /* read the header block */
  361.     if (read(fd,&rptr->rl_header,512) != 512) {
  362.         free(rptr);
  363.         close(fd);
  364.         return (db_nerror(BADHDR));
  365.     }
  366.  
  367.     /* close the relation file */
  368.     close(fd);
  369.  
  370.     /* extract header information */
  371.     rptr->rl_tcnt = db_cvword(rptr->rl_header.hd_tcnt);
  372.     rptr->rl_tmax = db_cvword(rptr->rl_header.hd_tmax);
  373.     rptr->rl_text = db_cvword(rptr->rl_header.hd_text);
  374.     rptr->rl_data = db_cvword(rptr->rl_header.hd_data);
  375.     rptr->rl_size = db_cvword(rptr->rl_header.hd_size);
  376.  
  377.     /* store the relation name */
  378.     strncpy(rptr->rl_name,rname,RNSIZE);
  379.  
  380.     /* link new relation into relation list */
  381.     rptr->rl_next = relations;
  382.     relations = rptr;
  383.  
  384.     /* return the new relation structure pointer */
  385.     return (rptr);
  386. }
  387.  
  388. /* seek - seek a tuple in a relation file */
  389. static int seek(rptr,tnum)
  390.   struct relation *rptr; unsigned int tnum;
  391. {
  392.     long offset;
  393.     offset = (long)rptr->rl_data + ((long)(tnum-1) * (long)rptr->rl_size);
  394.     return (lseek(rptr->rl_fd,offset,0) == offset);
  395. }
  396.  
  397. /* make_fname - make a relation name into a file name */
  398. static make_fname(fname,rname)
  399.   char *fname,*rname;
  400. {
  401.     strncpy(fname,rname,RNSIZE); fname[RNSIZE] = 0;
  402.     strcat(fname,".sdb");
  403. }
  404.  
  405. /* db_nerror - store the error code and return NULL */
  406. char *db_nerror(errcode)
  407.   int errcode;
  408. {
  409.     dbv_errcode = errcode;
  410.     return (NULL);
  411. }
  412.  
  413. /* db_ferror - store the error code and return FALSE */
  414. int db_ferror(errcode)
  415.   int errcode;
  416. {
  417.     dbv_errcode = errcode;
  418.     return (FALSE);
  419. }
  420.  
  421. /* db_cvword - convert 2 bytes to a word */
  422. int db_cvword(bytes)
  423.   char bytes[2];
  424. {
  425.     return (((bytes[1] & 0377) << 8) + (bytes[0] & 0377));
  426. }
  427.  
  428. /* db_cvbytes - convert a word to 2 bytes */
  429. db_cvbytes(word,bytes)
  430.   int word; char bytes[2];
  431. {
  432.     bytes[0] = word;
  433.     bytes[1] = word >> 8;
  434. }
  435.